package com.dx.chat.client;

import com.dx.chat.util.AdressUtil;
import com.dx.chat.util.AlertUtil;
import com.dx.chat.util.ByteUtil;
import javafx.scene.layout.BorderPane;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

/**
 * Description: 客户端的服务
 *
 * @author rockstarsteve
 * @version 1.0
 * @copyright Copyright (c) 电信
 * @since 2023/9/8
 */
@Slf4j
public class ClientService {

    /**
     * 发送文字
     *
     * @param clientInfoBean
     */
    public void sendMsg(ClientInfoBean clientInfoBean) {
        if (!clientInfoBean.isConnected()) {
            AlertUtil.alertWarn("提示", "尚未连接到服务器");
            return;
        }
        Socket socket = clientInfoBean.getSocket();
        try {
            OutputStream outputStream = socket.getOutputStream();
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
            // 获取文本框内容
            String sendMsg = clientInfoBean.getSendMsg();
            if (sendMsg.length() > 300) {
                AlertUtil.alertInfo("提示", "暂无法发送超过300个字的文字内容！");
                return;
            }
            if (sendMsg == null || "".equals(sendMsg)) {
                return;
            }
            byte[] textBytes = sendMsg.getBytes(StandardCharsets.UTF_8);
            byte[] sendBytes = new byte[textBytes.length + 5];
            byte[] addresByte = socket.getInetAddress().getAddress();
            sendBytes[0] = addresByte[0];
            sendBytes[1] = addresByte[1];
            sendBytes[2] = addresByte[2];
            sendBytes[3] = addresByte[3];
            sendBytes[4] = 0;
            for (int i = 0; i < textBytes.length; i++) {
                sendBytes[i + 5] = textBytes[i];
            }
            bufferedOutputStream.write(sendBytes);
            bufferedOutputStream.flush();
            String ipAddr = socket.getInetAddress().getHostAddress();
            clientInfoBean.setChatInfoString(clientInfoBean.getChatInfoString() + "客户端(" + ipAddr + ")：" + sendMsg + "\n");
            clientInfoBean.setSendMsg("");
        } catch (Exception ex) {
            log.error("客户端发送消息错误：{}", ex);
            AlertUtil.alertInfo("提示", "发送消息失败，请检查日志查看！");
        }
    }

    /**
     * 发送文件
     * <h1>>规则</h1>
     * <p1>4位ip位 1位内容标识位 4位头部长度位 1位文件开始标识位 文件名称位  文件内容开始 （1位内容标识位：0：文本，1：文件；1位文件开始标识位:0：开始，1：中间部分）</p>
     * <p1>4位ip位 1位内容标识位 4位头部长度位 1位文件开始标识位 文件名称位 文件内容中间</p>
     * <p1>4位ip位 1位内容标识位 4位头部长度位 1位文件开始标识位 文件名称位 文件内容后面</p>
     *
     * @param clientInfoBean
     */
    public void sendFile(ClientInfoBean clientInfoBean) {
        if (!clientInfoBean.isConnected()) {
            AlertUtil.alertWarn("提示", "尚未连接到服务器");
            return;
        }
        if (clientInfoBean.getFilePath() == null || "".equals(clientInfoBean.getFilePath())) {
            AlertUtil.alertWarn("提示", "还未选择文件");
            return;
        }

        try {
            File file = new File(clientInfoBean.getFilePath());
            Socket socket = clientInfoBean.getSocket();
            String fileName = file.getName();
            byte[] fileNameBytes = fileName.getBytes(StandardCharsets.UTF_8);
            int headLength = 10 + fileNameBytes.length;
            OutputStream outputStream = socket.getOutputStream();
            FileInputStream fileInputStream = new FileInputStream(file);
            //1.先把ip和头写过去
            byte[] addresByte = socket.getInetAddress().getAddress();
            //2.然后再把文件写过去
            int len = 0;
            byte[] fileBytes = new byte[1024 - headLength];
            boolean startFlag = true;
            while ((len = fileInputStream.read(fileBytes)) != -1) {
                byte[] newByteArray = ByteUtil.reviseArray(fileBytes, headLength);
                if (startFlag) {
                    newByteArray[9] = 0;
                    String localIpAddr = InetAddress.getLocalHost().getHostAddress();
                    clientInfoBean.setChatInfoString(clientInfoBean.getChatInfoString() + "客户端(" + localIpAddr + ")：正在发送\"" + fileName + "\"文件！\n");
                    startFlag = false;
                } else {
                    newByteArray[9] = 1;
                }
                newByteArray[0] = addresByte[0];
                newByteArray[1] = addresByte[1];
                newByteArray[2] = addresByte[2];
                newByteArray[3] = addresByte[3];
                newByteArray[4] = 1;
                //4位头部长度内容添加
                byte[] headLengthBytes = ByteUtil.intToBytes(headLength);
                for (int i = 0; i < headLengthBytes.length; i++) {
                    newByteArray[i + 5] = headLengthBytes[i];
                }
                //文件名称内容添加
                for (int i = 0; i < fileNameBytes.length; i++) {
                    newByteArray[i + 10] = fileNameBytes[i];
                }
                outputStream.write(newByteArray, 0, len + headLength);
            }
            outputStream.flush();
            String localIpAddr = InetAddress.getLocalHost().getHostAddress();
            clientInfoBean.setChatInfoString(clientInfoBean.getChatInfoString() + "客户端(" + localIpAddr + ")：发送\"" + fileName + "\"文件成功！\n");
            clientInfoBean.setFilePath("");
        } catch (Exception ex) {
            log.error("上传文件失败：{}", ex);
            AlertUtil.alertWarn("提示", "上传文件失败");
        }
    }

    /**
     * 选择文件
     *
     * @param clientInfoBean
     */
    public void chooseFile(ClientInfoBean clientInfoBean, BorderPane body) {
        Stage stage = (Stage) body.getScene().getWindow();
        FileChooser fileChooser = new FileChooser();
        File file = fileChooser.showOpenDialog(stage);
        if (file != null && file.exists()) {
            clientInfoBean.setFilePath(file.getAbsolutePath());
        }
    }

    /**
     * 连接服务器
     *
     * @param clientInfoBean
     */
    public void connection(ClientInfoBean clientInfoBean) {
        if (!AdressUtil.isIP(clientInfoBean.getIp())) {
            AlertUtil.alertWarn("提示", "服务器ip不正确");
            return;
        }
        if (!AdressUtil.isPort(clientInfoBean.getPort())) {
            AlertUtil.alertWarn("提示", "服务器端口不正确");
            return;
        }
        try {
            Socket socket = new Socket(clientInfoBean.getIp(), Integer.parseInt(clientInfoBean.getPort()));
            clientInfoBean.setSocket(socket);
            clientInfoBean.setChatInfoString(clientInfoBean.getChatInfoString() + "客户端成功连接服务器...\n");
        } catch (IOException e) {
            log.error("输入的ip和端口号有误或服务器不存在，创建连接出现失！！:{}", e);
            AlertUtil.alertWarn("警告", "输入的ip和端口号有误或服务器不存在，创建连接出现失败！");
        }
        new ClientConnectionThead(clientInfoBean).start();
        clientInfoBean.setConnected(true);
    }
}
